package cn.org.intelli.lims.o2oa.model;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import org.hibernate.annotations.SQLDelete;
import org.springframework.stereotype.Service;
import xyz.erupt.annotation.Erupt;
import xyz.erupt.annotation.EruptField;
import xyz.erupt.annotation.fun.DataProxy;
import xyz.erupt.annotation.query.Condition;
import xyz.erupt.annotation.sub_erupt.Drill;
import xyz.erupt.annotation.sub_erupt.Filter;
import xyz.erupt.annotation.sub_erupt.Link;
import xyz.erupt.annotation.sub_erupt.LinkTree;
import xyz.erupt.annotation.sub_field.Edit;
import xyz.erupt.annotation.sub_field.EditType;
import xyz.erupt.annotation.sub_field.View;
import xyz.erupt.annotation.sub_field.ViewType;
import xyz.erupt.annotation.sub_field.sub_edit.ReferenceTreeType;
import xyz.erupt.annotation.sub_field.sub_edit.Search;
import xyz.erupt.core.controller.EruptDataController;
import xyz.erupt.core.controller.EruptModifyController;
import xyz.erupt.core.view.Page;
import xyz.erupt.core.view.TableQueryVo;

import javax.annotation.Resource;
import javax.persistence.*;
import java.util.*;

@Service
@Getter
@Setter
@Entity
@Table(name = "lims_person", uniqueConstraints = {@UniqueConstraint(columnNames = {"name"})})
@SQLDelete(sql = "update lims_person set deleted = true, delete_time = now() where id = ?")
@Erupt(name = "人员信息", dataProxy = Person.class, linkTree = @LinkTree(field = "org"), filter = @Filter("Person.deleted = false"), drills = {@Drill(title = "资质", link = @Link(linkErupt = Qualification.class, joinColumn = "person.id"))})
public class Person implements DataProxy<Person> {
    @Id
    @EruptField(views = @View(title = "", type = ViewType.QR_CODE))
    private String id;
    @EruptField(views = @View(title = "姓名"), edit = @Edit(title = "姓名", search = @Search))
    private String name;
    @ManyToOne
    @EruptField(views = @View(title = "所属机构", column = "name"), edit = @Edit(title = "所属机构", type = EditType.REFERENCE_TREE, referenceTreeType = @ReferenceTreeType(pid = "parent.id")))
    private Org org;
    @ManyToMany
    @JoinTable(name = "lims_person_duty", joinColumns = @JoinColumn(name = "person_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "duty_id", referencedColumnName = "id"))
    @EruptField(edit = @Edit(title = "职责信息", type = EditType.TAB_TABLE_REFER))
    private Set<Duty> duties;
    @ManyToMany
    @JoinTable(name = "lims_person_train", joinColumns = @JoinColumn(name = "person_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "train_id", referencedColumnName = "id"))
    @EruptField(edit = @Edit(title = "培训信息", type = EditType.TAB_TABLE_REFER))
    private Set<Train> trains;
    @Column(name = "delete_time")
    private Date deleteTime;
    private Boolean deleted = false;

    @Override
    public void beforeAdd(Person person) {
        if (person.getId() == null) {
            person.setId(UUID.randomUUID().toString());
        }
    }

    @Transient
    @Resource
    private EruptModifyController eruptModifyController;
    @Transient
    @Resource
    private EruptDataController eruptDataController;
    @Transient
    private Gson gson = new Gson();

    @Override
    public void afterAdd(Person person) {
        JsonObject eruptUser = new JsonObject();
        eruptUser.addProperty("account", person.getName());
        eruptUser.addProperty("name", person.getName());
        eruptUser.addProperty("isMd5", true);
        eruptUser.addProperty("status", true);
        eruptUser.addProperty("passwordA", "intelli");
        eruptUser.addProperty("passwordB", "intelli");
        if (person.getOrg() != null) {
            Long eruptOrgId = getEruptOrgId(person.getOrg());
            if (eruptOrgId != null) {
                JsonObject eruptOrg = new JsonObject();
                eruptOrg.addProperty("id", eruptOrgId);
                eruptUser.add("eruptOrg", eruptOrg);
            }
        }
        eruptModifyController.addEruptData("EruptUser", eruptUser, null, null);
    }

    @SneakyThrows
    @Override
    public void afterUpdate(Person person) {
        JsonObject eruptUser = new JsonObject();
        Optional.ofNullable(person.getName()).ifPresent(name -> eruptUser.addProperty("account", name));
        Optional.ofNullable(person.getName()).ifPresent(name -> eruptUser.addProperty("name", name));
        if (person.getOrg() != null) {
            Long eruptOrgId = getEruptOrgId(person.getOrg());
            if (eruptOrgId != null) {
                JsonObject eruptOrg = new JsonObject();
                eruptOrg.addProperty("id", eruptOrgId);
                eruptUser.add("eruptOrg", eruptOrg);
            }
        }
        eruptModifyController.editEruptData("EruptUser", eruptUser);
    }

    @Override
    public void afterDelete(Person person) {
        Long eruptUserId = getEruptUserId(person);
        if (eruptUserId != null) {
            eruptModifyController.deleteEruptData("EruptUser", eruptUserId.toString());
        }
    }

    private Long getEruptOrgId(Org org) {
        TableQueryVo orgTableQueryVo = new TableQueryVo();
        orgTableQueryVo.setPageIndex(1);
        orgTableQueryVo.setPageSize(10);
        List<Condition> orgConditions = new ArrayList<>();
        orgConditions.add(new Condition("code", org.getId()));
        orgTableQueryVo.setCondition(orgConditions);
        Page page = eruptDataController.getEruptData("EruptOrg", orgTableQueryVo);
        Long eruptOrgId = null;
        if (page.getTotal() == 1) {
            eruptOrgId = (Long) page.getList().stream().findFirst().get().get("id");
        }
        return eruptOrgId;
    }

    private Long getEruptUserId(Person person) {
        TableQueryVo userTableQueryVo = new TableQueryVo();
        userTableQueryVo.setPageIndex(1);
        userTableQueryVo.setPageSize(10);
        List<Condition> orgConditions = new ArrayList<>();
        orgConditions.add(new Condition("account", person.getName()));
        userTableQueryVo.setCondition(orgConditions);
        Page page = eruptDataController.getEruptData("EruptUser", userTableQueryVo);
        Long eruptUserId = null;
        if (page.getTotal() == 1) {
            eruptUserId = (Long) page.getList().stream().findFirst().get().get("id");
        }
        return eruptUserId;
    }
}
